/*
 * Copyright (c) 2017-2019, Lindenis Tech. Ltd.
 * All rights reserved.
 *
 * File:
 *
 * Description:
 *
 * Author:
 *      xiaoshujun@lindeni.com
 *
 * Create Date:
 *      2019/08/08
 *
 * History:
 *
 */

#include <stdio.h>
#include <stdint.h>

#include "osal_uuid.h"

static uint64_t seed[2];

static uint64_t xorshift128plus(uint64_t *s) {
  /* http://xorshift.di.unimi.it/xorshift128plus.c */
  uint64_t s1 = s[0];
  const uint64_t s0 = s[1];
  s[0] = s0;
  s1 ^= s1 << 23;
  s[1] = s1 ^ s0 ^ (s1 >> 18) ^ (s0 >> 5);
  return s[1] + s0;
}

static int uuid_init(void)
{
    int res;
    FILE *fp = fopen("/dev/urandom", "rb");
    if (!fp)
    {
        return -1;
    }

    res = fread(seed, 1, sizeof(seed), fp);
    fclose(fp);

    if (res != sizeof(seed))
    {
        return -1;
    }

    return 0;
}

int ld_uuid_generate(char * dst)
{
    static const char *template = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx";
    static const char *chars = "0123456789abcdef";
    union { unsigned char b[16]; uint64_t word[2]; } s;
    const char *p;
    int i, n;

    /* init */
    if (0 != uuid_init())
    {
        return -1;
    }

    /* get random */
    s.word[0] = xorshift128plus(seed);
    s.word[1] = xorshift128plus(seed);

    /* build string */
    p = template;
    i = 0;
    while (*p)
    {
        n = s.b[i >> 1];
        n = (i & 1) ? (n >> 4) : (n & 0xf);
        switch (*p) {
            case 'x'  : *dst = chars[n];              i++;  break;
            case 'y'  : *dst = chars[(n & 0x3) + 8];  i++;  break;
            default   : *dst = *p;
        }
        dst++, p++;
    }
    *dst = '\0';

    return 0;
}
